<sg-frame state=${_self}>
  <table>
    <thead>
      <tr class="label column">
        <th class=top-left></th>
        ${columnNames.map(name => F`${{key:`col${name}`}}
        <th scope=col>${name}</th>
        `)}
      </tr>
    </thead>
    <!-- the below loops using schedule to print 2500+ components are heavily optimized -->
    <tbody>${schedule(rowNames, async rowName =>  await F`${{key:`row${rowName}`}}
      <tr>
        <th scope=row class="label row">${rowName}</th>
        ${schedule(columnNames, async colName => {
          const key = `${colName}${rowName}`;
          /** DON'T do this
            /* setting state within a render will cause
            /* unnecessary re-renders as well as race-condition errors
            if ( ! cell[key] ) {
              cell[key] = {key, formula: '', value: ''};
            }
          **/
          return await F`${{key}}
        <td>
          <!sg-cell data-key=${key} state=${cell[key]} />
        </td>
        `}, {batchSize: 5})}
      </tr>
    `, {batchSize: 1})
    }</tbody>
  </table>
  <p>
    You can use syntax like <code>= a1 * b2</code>. All regular JavaScript syntax and <code>Math</code> 
    functions work.
  </p>
</sg-frame>
